using System;
using System.Collections.Generic;
using System.IO;
using LogSystem;

#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
#endif

using UnityEngine;
using Random = UnityEngine.Random;

namespace Yoozoo.Gameplay.City
{
    [Serializable]
    public class CityEventSubConfig
    {
        public int eventId;
        public Vector2Int eventGird;
        public Vector2Int centerGrid;
    }
    
    [Serializable]
    public class CityEventConfig
    {
        public CityEventConfig()
        {
            eventConfigs = new List<CityEventSubConfig>();
        }
        public List<CityEventSubConfig> eventConfigs;
    }
    

    [Serializable]
    public class AreaEventConfig
    {
        [Serializable]
        public class AreaEventElement
        {
            public int id; // all
            public int type; // all
            public string condition; // all
            public int room_data; // client
            public string floor_space; // all
            public string pic; // client
            public string reward; // all
            public string change_building; // all
            public int pickup_cd; // client
            public int energy_cost; // all
        }

        public List<AreaEventElement> EventElements;
    }
    

    [Serializable]
    public class AreaTypeConfig
    {
        public int type;
        public GameObject prefab;
    }
    
    public class CityEventEditor : CityEditorBase
    {
        [Header("策划配置json文件路径")]
        public string eventInfoConfigPath;
        [Header("导出的事件配置路径")]
        public string areaEventConfigPath;

        [HideInInspector] // 现在不需要
        public List<AreaTypeConfig> areaTypeConfigs;
        private Dictionary<int, AreaTypeConfig> _areaTypeConfigMap;

        private Dictionary<Collider, int> _col2EventIdMap;
        private Dictionary<int, GameObject> _eventEntityMap;

        [SerializeField][HideInInspector]
        private List<int> _remainEvents;
        [SerializeField][HideInInspector]
        private List<int> _currentRemainEvents; // 当前剩余的事件



        public List<AreaEventConfig.AreaEventElement> allEventElements;
        private Dictionary<int, AreaEventConfig.AreaEventElement> _eventElementMap;

        [SerializeField]
        private CityEventConfig cityEventConfig;
        
        [SerializeField][DisplayOnly]
        private bool editing;
        private int _selectedIndex;
        private GameObject _selectedGameObject;

        private GameObject _eventRoot;
        
        [SerializeField][HideInInspector]
        private int filterEventId;
        
        public AreaEventConfig.AreaEventElement GetEventElement(int eventId)
        {
            _eventElementMap.TryGetValue(eventId, out var e);
            return e;
        }
        [HideInInspector]
        public int currentType = -1;  // 默认为全部
        public void FilterEvent(int type, int fId = 0)
        {
            currentType = type;
            
            _currentRemainEvents = new List<int>(1000);
            for (int i = 0; i < _remainEvents.Count; i++)
            {
                var element = GetEventElement(_remainEvents[i]);
                if (element!=null)
                {
                    if (element.type == type || type == -1)
                    {
                        if (fId == 0)
                        {
                            _currentRemainEvents.Add(_remainEvents[i]);
                        }
                        else
                        {
                            if (element.id == fId)
                            {
                                _currentRemainEvents.Add(_remainEvents[i]);
                            }
                        }
                   
                    }
                }
                else
                {
                    Debug.LogError(LogModule.City,$"没有这个id的事件:{_remainEvents[i]}");
                }
            }
            
            
            _currentRemainEvents.Sort((a, b) =>
            {
                return a > b ? 1 : -1;
            });
            
            SelectEvent(0);

        }

        public bool SelectEvent(int eventIndex)
        {
            if (eventIndex < 0) return false;
            
            _selectedIndex = -1;
            if (_selectedGameObject)
            {
                GameObject.DestroyImmediate(_selectedGameObject);
            }
            
            _selectedIndex = eventIndex;
            if (_selectedIndex >= _currentRemainEvents.Count) return false;
            
            var eventElement = GetEventElement(_currentRemainEvents[_selectedIndex]);
            _selectedGameObject = InstantiateEventObject(eventElement);
            return true;
        }

        public void ClearSelect()
        {
            _selectedIndex = -1;
            if (_selectedGameObject)
            {
                GameObject.DestroyImmediate(_selectedGameObject);
                _selectedGameObject = null;
            }
        }

        private GameObject InstantiateEventObject(AreaEventConfig.AreaEventElement eventElement)
        {
#if UNITY_EDITOR
            if (_eventRoot == null)
            {
                _eventRoot = new GameObject("Events");
                _eventRoot.transform.parent = cityRoot;
                _eventRoot.transform.position = Vector3.zero;
                
            }
            // DEBUG
            eventElement.pic = "Assets/Arts/Scene/City/Event001.prefab";

            var size = GetEventSize(eventElement);
            
            var p = AssetDatabase.LoadAssetAtPath<GameObject>(eventElement.pic);
            if (p)
            {
                GameObject o = GameObject.Instantiate(p);
                o.transform.localScale = new Vector3(cityCellSize.x * size.x, 0.001f, cityCellSize.z * size.y);
                o.transform.eulerAngles = new Vector3(0, 45, 0);

                o.transform.name = eventElement.id.ToString();
                o.transform.parent = _eventRoot.transform;
                
                Renderer renderer = o.GetComponent<Renderer>();
                MaterialPropertyBlock mpb = new MaterialPropertyBlock();
                renderer.GetPropertyBlock(mpb);
                mpb.SetColor("_Color", new Color(Random.Range(0, 255)/255f, Random.Range(0, 255)/255f, Random.Range(0, 255)/255f, 0.5f));
                renderer.SetPropertyBlock(mpb);
                
                var tc = o.GetComponentInChildren<UnityEngine.UI.Text>();
                if (tc)
                {
                    tc.text = eventElement.id.ToString();
                }
                return o;
            }
            return null;
#endif
            return null;
        }

        public Vector2Int GetEventSize(AreaEventConfig.AreaEventElement eventElement)
        {
            // 获得长宽
            Vector2Int size = new Vector2Int();
            try
            {
                string[] wh = eventElement.floor_space.Trim().Split(';');
                size = new Vector2Int(Int32.Parse(wh[0]), Int32.Parse(wh[1]));
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError($"请检查配表floor_space字段,事件ID：{eventElement.id}");
                Console.WriteLine(e);
                throw;
            }

            return size;
        }

        private void Init()
        {
#if UNITY_EDITOR
            _areaTypeConfigMap = new Dictionary<int, AreaTypeConfig>();
            if (areaTypeConfigs!=null)
            {
                foreach (var areaTypeConfig in areaTypeConfigs)
                {
                    _areaTypeConfigMap[areaTypeConfig.type] = areaTypeConfig;
                }
            }

            _col2EventIdMap = new Dictionary<Collider, int>();
            _eventEntityMap = new Dictionary<int, GameObject>();

            _remainEvents = new List<int>();
            _currentRemainEvents = new List<int>();

            
            //allEventElements

            // 载入所有可配置事件
            if (!File.Exists(eventInfoConfigPath)) return;

            var eventConfigText = AssetDatabase.LoadAssetAtPath<TextAsset>(eventInfoConfigPath).text;
            AreaEventConfig areaEventConfig = JsonUtility.FromJson<AreaEventConfig>(eventConfigText);
            allEventElements = areaEventConfig.EventElements;

            HashSet<int> existEvents = new HashSet<int>();
            _eventElementMap = new Dictionary<int, AreaEventConfig.AreaEventElement>();
            for (var i = 0; i < allEventElements.Count; i++)
            {
                var eventElement = allEventElements[i];
                _eventElementMap[eventElement.id] = eventElement;
            }
            
            // 载入已经编辑好的事件
            if (File.Exists(areaEventConfigPath))
            {
                var areaEventText = AssetDatabase.LoadAssetAtPath<TextAsset>(areaEventConfigPath).text;
                cityEventConfig = JsonUtility.FromJson<CityEventConfig>(areaEventText);
                CityEventConfig newCityEventConfig = new CityEventConfig();

                for (int i = 0; i < cityEventConfig.eventConfigs.Count; i++)
                {
                    var subCfg = cityEventConfig.eventConfigs[i];

                    if (_eventElementMap.ContainsKey(subCfg.eventId))
                    {
                        existEvents.Add(subCfg.eventId);
                        // 显示事件
                        var element = _eventElementMap[subCfg.eventId];
                        
                        // 获得长宽
                        Vector2Int size = GetEventSize(element);

                        Vector3 pos = Gird2CityPos(subCfg.centerGrid, size);

                        // 载入prefab
                        var eventObj = InstantiateEventObject(element);
                        Collider eventCollider = eventObj.GetComponent<Collider>();
                        if (eventCollider)
                        {
                            _col2EventIdMap[eventCollider] = subCfg.eventId;
                        }

                        _eventEntityMap[subCfg.eventId] = eventObj;
                        eventObj.transform.localPosition = pos;

                        newCityEventConfig.eventConfigs.Add(subCfg);
                    }
                    else
                    {
                        // 配表已经移除的事件不显示
                    }

                }
                cityEventConfig = newCityEventConfig;
            }
            else
            {
                cityEventConfig = new CityEventConfig();
            }
            

            _remainEvents = new List<int>(1000);
            _currentRemainEvents = new List<int>(1000);
            
            for (var i = 0; i < allEventElements.Count; i++)
            {
                var eventElement = allEventElements[i];
                _eventElementMap[eventElement.id] = eventElement;

                if (!existEvents.Contains(eventElement.id))
                {
                    _remainEvents.Add(eventElement.id);
                    _currentRemainEvents.Add(eventElement.id);
                }

            }
            
            _currentRemainEvents.Sort((a, b) =>
            {
                return a > b ? 1 : -1;
            });

            gridRenderer.transform.localScale = new Vector3((width) * cityCellSize.x * 0.1f,  1, (height) * cityCellSize.z * 0.1f);
            gridRenderer.sharedMaterial.SetTextureScale("_GridTex",new Vector2(width,height));

            StartCoroutine(GenerateGridCoordinateText());
#endif
        }

#if UNITY_EDITOR
        private ReorderableList _eventList;
        public void SetEventRenderList(ReorderableList eventList)
        {
            _eventList = eventList;
        }
#endif

        public void Begin()
        {
            editing = true;
            Init();
        }

        public void End()
        {
            Save();
            editing = false;
        }

        public void Save()
        {
#if UNITY_EDITOR
            if (!editing) return;
            var jsonText = JsonUtility.ToJson(cityEventConfig,false);
            FileStream fs = new FileStream(areaEventConfigPath, FileMode.Create, FileAccess.Write);
            using (StreamWriter writer = new StreamWriter(fs))
            {
                writer.Write(jsonText);
                writer.Flush();
                writer.Close();
                fs.Close();
            }
            var luaText = JsonToLua.ConvertLua(jsonText);
            var areaEventLuaPath = $"{Application.dataPath}/../Lua/modules/city/config/eventJsonConfig.lua";
            FileStream luafs = new FileStream(areaEventLuaPath, FileMode.Create, FileAccess.Write);
            using (StreamWriter writer = new StreamWriter(luafs))
            {
                writer.Write(luaText);
                writer.Flush();
                writer.Close();
                luafs.Close();
            }
            Debug.Log("导出结束！");
            AssetDatabase.Refresh();
#endif
        }
        
        private void Update()
        {
            if (!editing)
            {
                return;
            }


            // ctrl+中键移除
            if (Input.GetKey(KeyCode.LeftControl) && Input.GetMouseButton(2))
            {
                Ray camRay = cityCamera.ScreenPointToRay(Input.mousePosition);
                RaycastHit hit;
                if (Physics.Raycast(camRay, out hit,10000))
                {
                    if (_col2EventIdMap.TryGetValue(hit.collider, out int eventId))
                    {
                        _col2EventIdMap.Remove(hit.collider);

                        if (cityEventConfig.eventConfigs.Count > 0)
                        {
                            for (int i = cityEventConfig.eventConfigs.Count - 1; i >= 0; i--)
                            {
                                if (cityEventConfig.eventConfigs[i].eventId == eventId)
                                {
                                    cityEventConfig.eventConfigs.RemoveAt(i);
                                }
                            }
                        }

                        _eventEntityMap.TryGetValue(eventId, out GameObject eventObject);
                        if (eventObject)
                        {
                            _eventEntityMap.Remove(eventId);
                            GameObject.DestroyImmediate(eventObject);
                        }

                        _remainEvents.Add(eventId);
                        FilterEvent(currentType);
                        
                        _selectedIndex = -1;
                        if (_selectedGameObject)
                        {
                            GameObject.DestroyImmediate(_selectedGameObject);
                            _selectedGameObject = null;
                        }
                    }
                }
            }

            if (!_selectedGameObject)
            {
                return;
            }
                        
            var eventElement = GetEventElement(_currentRemainEvents[_selectedIndex]);
            Vector2Int size = GetEventSize(eventElement);
            GetClickPos(Input.mousePosition, out Vector3 hitPos);
            Vector2Int alignGrid;
            Vector3 alignPos;
            
            alignPos = AlignGridWorld(hitPos, size, out alignGrid);
            _selectedGameObject.transform.position = alignPos;

            // 右键放置
            if (Input.GetMouseButton(1))
            {
                _eventEntityMap[eventElement.id] = _selectedGameObject;
                Collider col = _selectedGameObject.GetComponent<Collider>();
                _col2EventIdMap[col] = eventElement.id;

                cityEventConfig.eventConfigs.Add(new CityEventSubConfig()
                {
                    eventId = eventElement.id,
                    centerGrid = alignGrid,
                    eventGird = CenterGird2EventGird(alignGrid,alignPos,size)
                });
                
                _currentRemainEvents.Remove(eventElement.id);
                _remainEvents.Remove(eventElement.id);
                
                _selectedIndex = -1;
                _selectedGameObject = null;
            }

        }

        public Vector3 AlignGridWorld(Vector3 pos,Vector2Int size,out Vector2Int grid)
        {
            grid = GetGrid(pos);
            return Gird2CityPos(grid, size);
        }
        
        public Vector2Int CenterGird2EventGird(Vector2Int centerGrid,Vector3 localPos,Vector2Int size)
        {
            float negCityViewRad = -Mathf.PI * gridViewAngleY / 180.0f;
            float negCosCityViewRad = Mathf.Cos(negCityViewRad);
            float negSinCityViewRad = Mathf.Sin(negCityViewRad);
            
            // 局部坐标旋转到视觉坐标
            float ox = localPos.x;
            float oz = localPos.z;

            localPos.x = negCosCityViewRad * ox + negSinCityViewRad * oz;
            localPos.z = -negSinCityViewRad * ox + negCosCityViewRad * oz;

            Vector3 pos = new Vector3(
                localPos.x - size.x * cityCellSize.x * 0.5f, 
                0, 
                localPos.z - size.y * cityCellSize.z * 0.5f);

            Vector3 bottomLeft = new Vector3(-width * cityCellSize.x * 0.5f, 0, -height * cityCellSize.z * 0.5f);

            pos -= bottomLeft;
            int gridX = GetFloat2IntValue(pos.x / cityCellSize.x);
            int gridZ = GetFloat2IntValue(pos.z / cityCellSize.z);
            return new Vector2Int(gridX, gridZ);
        }
        
        public Vector3 Gird2CityPos(Vector2Int grid,Vector2Int size)
        {
            Vector3 pos = Vector3.zero;

            pos.x = grid.x * cityCellSize.x;
            pos.z = grid.y * cityCellSize.z;
            
            Vector3 bottomLeft = new Vector3(-width * cityCellSize.x * 0.5f, 0, -height * cityCellSize.z * 0.5f);

            pos += bottomLeft;

            pos = pos + new Vector3(
                size.x % 2 * cityCellSize.x * 0.5f,
                0,
                size.y % 2 * cityCellSize.z * 0.5f);

            
            float cityViewRad = Mathf.PI * gridViewAngleY / 180.0f;
            float cosCityViewRad = Mathf.Cos(cityViewRad);
            float sinCityViewRad = Mathf.Sin(cityViewRad);


            float ox = pos.x;
            float oz = pos.z;

            pos.x = cosCityViewRad * ox + sinCityViewRad * oz;
            pos.z = -sinCityViewRad * ox + cosCityViewRad * oz;

            return pos;
        }
        
        
        
    }
}
